package com.jsgt.greekfire.ui.wallet.assets

import android.Manifest
import android.app.Activity
import android.content.Intent
import android.text.TextUtils
import android.view.View
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.fhx.core.base.BaseActivity
import com.fhx.core.scan.android.CaptureActivity
import com.fhx.core.utils.LogUtils
import com.fhx.core.utils.ToastUtils
import com.ftd.livepermissions.LivePermissions
import com.ftd.livepermissions.PermissionResult
import com.google.gson.Gson
import com.google.protobuf.ByteString
import com.jsgt.greekfire.App
import com.jsgt.greekfire.ENTRUST_NUM
import com.jsgt.greekfire.R
import com.jsgt.greekfire.SCAN_RESULT
import com.jsgt.greekfire.ui.dialog.DialogUtils
import com.jsgt.greekfire.common.util.UtilsBigDecimal
import com.jsgt.greekfire.dao.model.IdentityBean
import com.jsgt.greekfire.dao.model.IdentityWallet
import com.jsgt.greekfire.dao.viewmodel.WalletViewModel
import com.jsgt.greekfire.ui.mine.user.address.AddressActivity
import com.jsgt.greekfire.viewmodel.EntrustViewModel
import com.jsgt.greekfire.viewmodel.UserViewModel
import kotlinx.android.synthetic.main.activity_send.*
import org.altoro.common.crypto.Sha256Sm3Hash
import org.altoro.common.crypto.SignUtils
import org.bouncycastle.util.encoders.Hex
import java.math.BigInteger

class SendActivity : BaseActivity(), View.OnClickListener {
    private val userViewModel1: UserViewModel by lazy {
        ViewModelProvider(App.context).get(UserViewModel::class.java)
    }
    private val userViewModel: UserViewModel by lazy {
        ViewModelProvider(this).get(UserViewModel::class.java)
    }
    private val walletViewModel: WalletViewModel by lazy {
        ViewModelProvider(this).get(WalletViewModel::class.java)
    }
    private val entrustViewModel: EntrustViewModel by lazy {
        ViewModelProvider(this).get(EntrustViewModel::class.java)
    }
    private var identityBean: IdentityBean? = null
    private var wallet: IdentityWallet? = null
    private var balance = 0.0
    private var launch: ActivityResultLauncher<Intent>? = null

    override fun needFitsSystemWindows(): Boolean {
        return false
    }

    override fun getLayoutId(): Int {
        return R.layout.activity_send
    }

    override fun main() {
        setStatusBar(R.color.transparent, false, R.color.white)
        wallet = intent.getParcelableExtra("wallet")
        if (wallet == null) {
            finish()
        }
        title = String.format(getString(R.string.transfer_title1), wallet!!.key)
        txvBalance.text =
            String.format(getString(R.string.transfer_balance), balance.toString(), wallet!!.key)
        txvOk.setOnClickListener(this)
        imvScan.setOnClickListener(this)
        imvAddressBook.setOnClickListener(this)

        walletViewModel.getIdentity(wallet!!.identityId)?.observe(this, Observer {
            identityBean = it
        })
        userViewModel1.getAccount(wallet!!.address!!, "true")
        userViewModel1.getAccountLiveData.observe(this, Observer {
            if (it != null) {
                if (!TextUtils.isEmpty(it.balance)) {
                    balance = UtilsBigDecimal.div(it.balance!!, ENTRUST_NUM)
                    txvBalance.text =
                        String.format(
                            getString(R.string.transfer_balance),
                            balance.toString(),
                            wallet!!.key
                        )
                }
            }
        })
        userViewModel.transferLiveData.observe(this, Observer {
            if (it != null) {
                try {
                    val cryptoEngine = SignUtils.fromPrivate(
                        Hex.decode(
                            BigInteger(identityBean!!.getPriKeyByAES()).toString(16)
                        ), true
                    )
                    val rawData = Sha256Sm3Hash.of(Hex.decode(it.raw_data_hex))
                    val sig =
                        ByteString.copyFrom(cryptoEngine.Base64toBytes(cryptoEngine.signHash(rawData.bytes)))
                    val signature = Hex.toHexString(sig.toByteArray())
                    it.signature = signature
                    val data = Gson()
                    entrustViewModel.broadcasttransaction(data.toJson(it))
                } catch (e: Exception) {
                    LogUtils.error(e.message)
                    ToastUtils.show(R.string.data_error)
                    showProgress(false)
                    txvOk.isEnabled = true
                }
            }
        })
        userViewModel.errorLiveData.observe(this, Observer {
            ToastUtils.show(it.toString())
            showProgress(false)
            txvOk.isEnabled = true
        })
        entrustViewModel.broadcasttransactionListData.observe(this, Observer {
            showProgress(false)
            if (it != null) {
                if (!TextUtils.isEmpty(it.txid)) {
                    showProgress(false)
                    txvOk.isEnabled = true
                    finish()
                } else {
                    ToastUtils.show(R.string.data_error)
                    showProgress(false)
                    txvOk.isEnabled = true
                }
            }
        })

        launch = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            if (it.resultCode == Activity.RESULT_OK) {
                var content = it.data?.getStringExtra(SCAN_RESULT)
                if (content.isNullOrEmpty()) {
                    content = it.data?.getStringExtra("address")
                }
                edtAddress.setText(content)
                edtAddress.setSelection(edtAddress.text.length)
            }
        }
    }

    override fun onClick(v: View?) {
        when (v?.id) {
            R.id.txvOk -> {
                if (edtAddress.text.isNullOrEmpty()) {
                    ToastUtils.show(R.string.transfer_input_address)
                    return
                } else if (edtAmount.text.isNullOrEmpty()) {
                    ToastUtils.show(R.string.transfer_input_amount)
                    return
                } else if (edtAmount.text.toString().toDouble() > balance) {
                    ToastUtils.show(R.string.transfer_over_balance)
                    return
                } else {
                    if (identityBean != null) {
                        DialogUtils.showInputPwdDialog(
                            this, identityBean!!.password
                        ) {
                            showProgress(true)
                            txvOk.isEnabled = false
                            val amount =
                                UtilsBigDecimal.mul(edtAmount.text.toString(), ENTRUST_NUM, 0)!!
                                    .toBigInteger()
                            userViewModel.transfer(
                                wallet!!.address!!,
                                edtAddress.text.toString(),
                                amount,
                                "true"
                            )
                        }
                    }
                }
            }
            R.id.imvScan -> {
                LivePermissions(this).request(
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.CAMERA
                ).observe(this, Observer {
                    when (it) {
                        is PermissionResult.Grant -> {
                            launch?.launch(Intent(this, CaptureActivity::class.java))
                        }
                        is PermissionResult.Rationale -> {

                        }
                        is PermissionResult.Deny -> {
                            ToastUtils.show(R.string.permission_denied)
                        }
                    }
                })
            }
            R.id.imvAddressBook -> {
                launch?.launch(
                    Intent(
                        this,
                        AddressActivity::class.java
                    ).putExtra(AddressActivity.PAGE_TYPE, AddressActivity.TRANSFER)
                )
            }
        }
    }
}